﻿#region Copyright (c) 2011, thinktecture (http://www.thinktecture.com)

/*
   thinktecture.UIAnnotations was developed by Jörg Neumann.
   Copyright (c) 2011, thinktecture (http://www.thinktecture.com).
   All rights reserved, comes as-is and without any warranty. Use of this
   source file is governed by the license which is contained in LICENSE.TXT 
   in the distribution.
*/

#endregion

using System;
using System.Windows;
using System.Windows.Documents;
using System.Windows.Media.Imaging;
using System.Windows.Controls;

namespace Thinktecture.UIAnnotations
{
    public class ElementTrackerAdorner : Adorner, IDisposable
    {

        #region Private Variables
        
        private bool _showTracker;
        private FrameworkElement _focusElement;
        private ExtensionImageAlignment _alignment;
        private bool _focusEventsRegistered = false;
        private bool _focus = false;

        #endregion

        #region Constructors

        public ElementTrackerAdorner(UIElement adornedElement)
            : base(adornedElement)
        {
            this.Focusable = false;
            _showTracker = true;
            _alignment = ExtensionImageAlignment.Right;
        }

        public ElementTrackerAdorner(UIElement adornedElement, 
            bool showTracker,
            ExtensionImageAlignment alignment)
            : base(adornedElement)
        {
            this.Focusable = false;
            _showTracker = showTracker;
            _alignment = alignment;
        }

        #endregion

        #region Overrides

        protected override void OnRender(System.Windows.Media.DrawingContext drawingContext)
        {
            Rect targetRect;
            if (this.Alignment == ExtensionImageAlignment.Right)
            {
                targetRect = new Rect(
                    new Point(this.AdornedElement.RenderSize.Width + 3, (this.AdornedElement.RenderSize.Height - 18) / 2),
                    new Size(18, 18));
            }
            else
            {
                targetRect = new Rect(
                    new Point(-20, (this.AdornedElement.RenderSize.Height - 17) / 2),
                    new Size(18, 18));
            }
            if (_showTracker)
            {
                if (!_focusEventsRegistered)
                {
                    _focusElement = this.AdornedElement as FrameworkElement;
                    if (_focusElement is DatePicker)
                    {
                        DatePicker picker = this.AdornedElement as DatePicker;
                        _focusElement = picker.Template.FindName("PART_TextBox", picker) as FrameworkElement;
                    }
                    if (_focusElement != null)
                    {
                        _focusElement.AddHandler(FrameworkElement.GotFocusEvent, new RoutedEventHandler(OnGotFocus));
                        _focusElement.AddHandler(FrameworkElement.LostFocusEvent, new RoutedEventHandler(OnLostFocus));
                    }
                    _focusEventsRegistered = true;
                }
                if (_focus)
                {
                    BitmapImage trackerIcon = new BitmapImage();
                    trackerIcon.BeginInit();
                    Uri imageUri = new Uri("pack://application:,,,/Thinktecture.UIAnnotations;component/Images/ArrowBack.png");
                    if (_alignment == ExtensionImageAlignment.Left)
                        imageUri = new Uri("pack://application:,,,/Thinktecture.UIAnnotations;component/Images/ArrowFore.png");
                    trackerIcon.UriSource = imageUri;
                    trackerIcon.EndInit();
                    drawingContext.DrawImage(trackerIcon, targetRect);
                }
            }
        }

        #endregion

        #region Public Properties

        public ExtensionImageAlignment Alignment
        {
            get { return _alignment; }
            set { _alignment = value; this.InvalidateVisual(); }
        }

        public bool ShowTracker
        {
            get { return _showTracker; }
            set { _showTracker = value; this.InvalidateVisual(); }
        }

        #endregion

        #region Event Handling

        private void OnGotFocus(object sender, RoutedEventArgs e)
        {
            _focus = true;
            this.InvalidateVisual();
        }

        private void OnLostFocus(object sender, RoutedEventArgs e)
        {
            _focus = false;
            this.InvalidateVisual();
        }

        #endregion

        #region IDisposable Members

        public void Dispose()
        {
            if (_focusElement != null)
            {
                _focusElement.RemoveHandler(FrameworkElement.GotFocusEvent, new RoutedEventHandler(OnGotFocus));
                _focusElement.RemoveHandler(FrameworkElement.LostFocusEvent, new RoutedEventHandler(OnLostFocus));
                _focusElement = null;
            }
        }

        #endregion

    }
}
